﻿using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

namespace MetadataDesignerLibrary
{
    public class FieldDefinitionRule : ILRule<FieldDefinitionHandle>
    {
        [ILInfo(true)]
        public string Name { get; }

        [ILInfo]
        public FieldAttributes Attributes { get; }

        [ILInfo(ILInfoParseMethod.AsEntityHandleCollection)]
        public CustomAttributeHandleCollection CustomAttributes { get; }

        [ILInfo(true, ILInfoParseMethod.AsEntityHandle)]
        public TypeDefinitionHandle DeclaringType { get; }

        [ILInfo(true, ILInfoParseMethod.AsEntityHandle)]
        public ConstantHandle DefaultValue { get; }

        [ILInfo]
        public int Offset { get; }

        [ILInfo]
        public int RelativeVirtualAddress { get; }

        public byte[] Signature { get; }
        public BlobHandle MarshallingDescriptor { get; }

        public FieldDefinitionRule(
            FieldAttributes attributes,
            string name,
            byte[] signature)
            : base()
        {
            Attributes = attributes;
            Name = name;
            Signature = signature;
        }

        public FieldDefinitionRule(MetadataReader reader, FieldDefinitionHandle fieldDefinitionHandle)
            : base(reader)
        {
            FieldDefinition fieldDefinition = reader.GetFieldDefinition(fieldDefinitionHandle);
            Attributes = fieldDefinition.Attributes;
            Name = reader.GetString(fieldDefinition.Name);
            Signature = reader.GetBlobBytes(fieldDefinition.Signature);
            CustomAttributes = fieldDefinition.GetCustomAttributes();
            DeclaringType = fieldDefinition.GetDeclaringType();
            DefaultValue = fieldDefinition.GetDefaultValue();
            MarshallingDescriptor = fieldDefinition.GetMarshallingDescriptor();
            Offset = fieldDefinition.GetOffset();
            RelativeVirtualAddress = fieldDefinition.GetRelativeVirtualAddress();
        }

        public override FieldDefinitionHandle Write(MetadataDesigner designer)
        {
            MetadataBuilder builder = designer.Builder;
            FieldDefinitionHandle fieldDefinitionHandle = builder.AddFieldDefinition(
                attributes: Attributes,
                name: Name == null ? default : builder.GetOrAddString(Name),
                signature: Signature == null ? default : builder.GetOrAddBlob(Signature));
            designer.FieldDefinitionNumber.Increment();
            return fieldDefinitionHandle;
        }
    }
}